package cn.glutnn.auth.domain.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.glutnn.auth.application.entity.AuthUserEnum;
import cn.glutnn.auth.common.enums.IsDeletedFlagEnum;
import cn.glutnn.auth.domain.constants.AuthConstants;
import cn.glutnn.auth.domain.convert.AuthUserConverter;
import cn.glutnn.auth.domain.entity.AuthUserBO;
import cn.glutnn.auth.domain.redis.RedisUtil;
import cn.glutnn.auth.domain.service.AuthUserDomainService;
import cn.glutnn.auth.infra.basic.entity.*;
import cn.glutnn.auth.infra.basic.service.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.Gson;
import io.micrometer.common.util.StringUtils;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Author:   msh
 * Date:     2025/1/13 下午5:11
 * Description:
 */

@Service
@Slf4j
public class AuthUserDomainServiceImpl implements AuthUserDomainService {
    @Resource
    private AuthUserService authUserService;
    @Resource
    private AuthRoleService authRoleService;
    @Resource
    private AuthUserRoleService authUserRoleService;
    @Resource
    private AuthRolePermissionService authRolePermissionService;
    @Resource
    private AuthPermissionService authPermissionService;

    @Resource
    private RedisUtil redisUtil;
    private String authPermissionPrefix = "auth:permission:";
    private String authRolePrefix = "auth:role:";

    private final String LOGIN_PREFIX = "loginCode";

    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public Boolean register(AuthUserBO authUserBO) {
        AuthUser authUser = AuthUserConverter.INSTANCE.convertBoToEntity(authUserBO);
        // 判断用户是否存在, 如果存在则返回true
        LambdaQueryWrapper<AuthUser> authUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        authUserLambdaQueryWrapper.eq(AuthUser::getUserName, authUser.getUserName());
        if (authUserService.getOne(authUserLambdaQueryWrapper) != null) {
            return true;
        }
        if (!StringUtils.isBlank(authUser.getPassword())) {
            authUser.setPassword(SaSecureUtil.md5(authUser.getPassword()));
        }
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        authUser.setStatus(AuthUserEnum.OPEN.getCode());
        boolean save = authUserService.save(authUser);
        // 建立角色和用户关系
        LambdaQueryWrapper<AuthRole> authRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        authRoleLambdaQueryWrapper.eq(AuthRole::getRoleKey, AuthConstants.NORMAL_USER);
        AuthRole authRole = authRoleService.getOne(authRoleLambdaQueryWrapper);
        Long roleId = authRole.getId();
        Long userId = authUser.getId();
        AuthUserRole authUserRole = new AuthUserRole();
        authUserRole.setUserId(userId);
        authUserRole.setRoleId(roleId);
        boolean save1 = authUserRoleService.save(authUserRole);

        // 缓存角色信息
        String roleKey = redisUtil.buildKey(authRolePrefix, authUser.getUserName());
        LinkedList<AuthRole> authRoles = new LinkedList<>();
        authRoles.add(authRole);
        redisUtil.set(roleKey, new Gson().toJson(authRoles));
        // 缓存权限信息
//        AuthRolePermission authRolePermission = new AuthRolePermission();
//        authRolePermission.setRoleId(roleId);
        // 获取权限信息
        LambdaQueryWrapper<AuthRolePermission> authRolePermissionLambdaQueryWrapper = new LambdaQueryWrapper<>();
        authRolePermissionLambdaQueryWrapper.eq(AuthRolePermission::getRoleId, roleId);
        List<AuthRolePermission> authRolePermissions = authRolePermissionService.
                list(authRolePermissionLambdaQueryWrapper);
        List<Long> permissionIds = authRolePermissions.stream().map(AuthRolePermission::getPermissionId)
                .collect(Collectors.toList());
        LambdaQueryWrapper<AuthPermission> authPermissionLambdaQueryWrapper = new LambdaQueryWrapper<>();
        authPermissionLambdaQueryWrapper.in(AuthPermission::getId, permissionIds);
        List<AuthPermission> authPermissions = authPermissionService.listByIds(permissionIds);
        String permissionKey = redisUtil.buildKey(authPermissionPrefix, authUser.getUserName());
        redisUtil.set(permissionKey, new Gson().toJson(authPermissions)); // 缓存权限信息
        return save && save1;
    }

    @Override
    public Boolean update(AuthUserBO authUserBO) {
        AuthUser authUser = AuthUserConverter.INSTANCE.convertBoToEntity(authUserBO);
        return authUserService.updateById(authUser);
    }

    @Override
    public Boolean delete(AuthUserBO authUserBO) {
        AuthUser authUser = AuthUserConverter.INSTANCE.convertBoToEntity(authUserBO);
        authUser.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());
        return authUserService.updateById(authUser);
    }

    @Override
    public SaTokenInfo doLogin(String validCode) {
        String loginKey = redisUtil.buildKey(LOGIN_PREFIX, validCode);
        String openId = redisUtil.get(loginKey);
        if (StringUtils.isBlank(openId)) {
            return null;
        }
        AuthUserBO authUserBO = new AuthUserBO();
        authUserBO.setUserName(openId);
        this.register(authUserBO);
        StpUtil.login(openId);
        return StpUtil.getTokenInfo();
    }

    @Override
    public AuthUserBO getUserInfo(AuthUserBO authUserBO) {
        AuthUser authUser = AuthUserConverter.INSTANCE.convertBoToEntity(authUserBO);
        AuthUser userInfo = authUserService.getOne(new LambdaQueryWrapper<AuthUser>().eq(AuthUser::getUserName, authUser.getUserName()));
        return AuthUserConverter.INSTANCE.convertEntityToBo(userInfo);
    }
}
